using System.Collections.Generic;
using Headsight.BPMN2WF.BPMN.Schemas;
using Headsight.BPMN2WF.Testing.TestObjCtors;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Rhino.Mocks;

namespace Headsight.BPMN2WF.BPMN.Model
{
    [TestClass]
    public class BPMNProcessFactoryBPMNFlowNodeTest
    {
        private BPMNFlowNodeFactory _sut;
        private tProcessCtor _tProcCtor;
        private tFlowNode _flowNode1;
        private tFlowNode _flowNode2;
        private tSequenceFlow _tSeqFlow;
        private BPMNArgumentFactory _bpmnMFacArgs;
        private BPMNProcessFactoryParams _bpmnMFacParams;

        [TestInitialize]
        public void SetUp()
        {
            _tProcCtor = new tProcessCtor();
            _flowNode1 = new tFlowNodeCtor().WithId("_1").Create();
            _flowNode2 = new tFlowNodeCtor().WithId("_2").Create();
            _tSeqFlow = new tSequenceFlowCtor().Create();

            _bpmnMFacArgs = MockRepository.GenerateStub<BPMNArgumentFactory>();

            _bpmnMFacParams = new BPMNModelFactoryParamsCtor().With(_bpmnMFacArgs).Create();

            _sut = new BPMNFlowNodeFactoryImpl();
        }

        [TestMethod]
        public void CreateBPMNFlowNodes_in_case_of_0_tFlowNodes()
        {
            var tProcess = _tProcCtor.With(_tSeqFlow).Create();
            var bpmnSeqFlows = new List<BPMNSequenceFlow>();
            
            var actual = _sut.CreateBPMNFlowNodes(tProcess, bpmnSeqFlows, _bpmnMFacParams);

            Assert.AreEqual(0, actual.Count);
        }

        [TestMethod]
        public void CreateBPMNFlowNodes_in_case_of_1_tFlowNodes_but_not_BPMNSequenceFlows()
        {
            var tProcess = _tProcCtor.With(_flowNode1).Create();
            var bpmnSeqFlows = new List<BPMNSequenceFlow>();

            var actual = _sut.CreateBPMNFlowNodes(tProcess, bpmnSeqFlows, _bpmnMFacParams);

            Assert.AreEqual(1, actual.Count);
        }

        [TestMethod]
        public void CreateBPMNFlowNodes_in_case_of_1_tFlowNodes_1_BPMNSequenceFlow_in_1_BPMNSequenceFlow_out()
        {
            var bpmnSeqFlowIn = new BPMNSequenceFlowCtor().WithFlowTo(_flowNode1).Create();
            var bpmnSeqFlowOut = new BPMNSequenceFlowCtor().WithFlowFrom(_flowNode1).Create();

            var tProcess = _tProcCtor.With(_flowNode1).Create();
            var bpmnSeqFlows = new List<BPMNSequenceFlow> { bpmnSeqFlowIn, bpmnSeqFlowOut };

            var actual = _sut.CreateBPMNFlowNodes(tProcess, bpmnSeqFlows, _bpmnMFacParams);

            Assert.AreEqual(1, actual.Count);
            Assert.AreSame(_flowNode1, actual[0].TElement);
        }

        [TestMethod]
        public void CreateBPMNFlowNodes_in_case_of_2_tFlowNodes_each_2_BPMNSequenceFlow()
        {
            var bpmnSeqFlowIn1 = new BPMNSequenceFlowCtor().WithFlowTo(_flowNode1).Create();
            var bpmnSeqFlowIn2 = new BPMNSequenceFlowCtor().WithFlowTo(_flowNode1).Create();
            var bpmnSeqFlowIn3 = new BPMNSequenceFlowCtor().WithFlowTo(_flowNode2).Create();
            var bpmnSeqFlowIn4 = new BPMNSequenceFlowCtor().WithFlowTo(_flowNode2).Create();

            var tProcess = _tProcCtor.With(_flowNode1, _flowNode2).Create();
            var bpmnSeqFlows = new List<BPMNSequenceFlow> { bpmnSeqFlowIn1, bpmnSeqFlowIn2, bpmnSeqFlowIn3, bpmnSeqFlowIn4 };

            var actual = _sut.CreateBPMNFlowNodes(tProcess, bpmnSeqFlows, _bpmnMFacParams);

            Assert.AreEqual(2, actual.Count);
            
            Assert.AreSame(_flowNode1, actual[0].TElement);
            Assert.AreSame(_flowNode2, actual[1].TElement);
        }

        [TestMethod]
        public void CreateBPMNFlowNodes_ArgumentsIn_and_ArgumentsOut_are_retrieved_and_set()
        {
            var tProcess = _tProcCtor.With(_flowNode1, _flowNode2).Create();
            var bpmnSeqFlows = new List<BPMNSequenceFlow>();

            var bpmnParams1 = new List<BPMNArgument>();
            var bpmnParams2 = new List<BPMNArgument>();
            var bpmnParams3 = new List<BPMNArgument>();
            var bpmnParams4 = new List<BPMNArgument>();

            _bpmnMFacArgs.Expect(x => x.CreateArgumentsIn(_flowNode1)).Return(bpmnParams1);
            _bpmnMFacArgs.Expect(x => x.CreateArgumentsOut(_flowNode1)).Return(bpmnParams2);
            _bpmnMFacArgs.Expect(x => x.CreateArgumentsIn(_flowNode2)).Return(bpmnParams3);
            _bpmnMFacArgs.Expect(x => x.CreateArgumentsOut(_flowNode2)).Return(bpmnParams4);

            var actual = _sut.CreateBPMNFlowNodes(tProcess, bpmnSeqFlows, _bpmnMFacParams);

            Assert.AreSame(bpmnParams1, actual[0].ArgumentsIn);
            Assert.AreSame(bpmnParams2, actual[0].ArgumentsOut);
            Assert.AreSame(bpmnParams3, actual[1].ArgumentsIn);
            Assert.AreSame(bpmnParams4, actual[1].ArgumentsOut);
        }
    }
}